using System.Collections.Generic;
using CthulhuDomain.Services;
using Microsoft.Xna.Framework;

namespace CthulhuDomain.GameEntities
{
  public sealed class DomainEntityMatrix
  {
    private string[,] Schema { get; set; }
    private readonly DomainEntity[,] matrix;
    private const int DEFAULTSIDE = 5;
    private readonly DomainFactory domainFactory;
    private readonly int xSide;
    private readonly int ySide;

    public int EntityCount() {
      var result = 0;

      for (var i = 0; i < matrix.GetLength(0); i++) {
        for (var j = 0; j < matrix.GetLength(1); j++) {
          if (matrix[i, j] == null) continue;
          result++;
        }
      }

      return result;
    }

    public DomainEntity[,] Matrix {
      get { return matrix; }
    }

    public DomainEntityMatrix(string[,] schema) {
      Schema = schema;
      matrix = new DomainEntity[schema.GetLength(0), schema.GetLength(1)];
    }

    public void LoadContent(IContentManager Content, IRectangle Context) {
      for (var i = 0; i < Schema.GetLength(0); i++)
        for (var j = 0; j < Schema.GetLength(1); j++) {
          var setUp = new DomainEntitySetUp(Schema[i, j]);
          if (setUp.TypeEntity != DomainFactory.eTypeEntity.None)
          {
            var entityState = EntityStateFactory.GetFactory(setUp.TypeEntity).CreateEntityState();
            entityState.LifePoints = setUp.LifePoint;
            entityState.StartingPosition = new Vector2Adapter(
              DomainFactory.GetFactory(setUp.TypeEntity).CreateEntity(Content).Width*i +
              (Context.Width/2) -
              ((DomainFactory.GetFactory(setUp.TypeEntity).CreateEntity(Content).Width*xSide)/2),
              DomainFactory.GetFactory(setUp.TypeEntity).CreateEntity(Content).Height*j + 25);
            matrix[i, j] = DomainFactory.GetFactory(setUp.TypeEntity).CreateEntity(Content, entityState);
            matrix[i, j].Speed = Speed;
          }
          else
            matrix[i, j] = null;
        }
    }

    public void Update(IRectangle context, IGameTime time) {
      for (var i = 0; i < XLength; i++)
        for (var j = 0; j < YLength; j++) {
          if (matrix[i, j] == null) continue;
          if (matrix[i, j].LifePoint == -2) {
            matrix[i, j] = null;
            break;
          }

          matrix[i, j].Speed = matrix[i, j].Speed > 0 ? matrix[i, j].Speed = Speed : matrix[i, j].Speed = Speed * -1;
          matrix[i, j].Move(context, time);
          matrix[i, j].Update(context, time);
        }
    }

    public void Draw(ISpriteBatch spriteBatch) {
      for (var i = 0; i < XLength; i++)
        for (var j = 0; j < YLength; j++)
          if (matrix[i, j] != null)
            matrix[i, j].Draw(spriteBatch);
    }

    int GetLength(int axis) {
      return Matrix.GetLength(axis);
    }
    public int XLength {
      get {
        return GetLength(0);
      }
    }
    public int YLength {
      get {
        return GetLength(1);
      }
    }

    public float BulletSpeed { get; set; }

    private float _speed = 4f;
    public float Speed
    {
      get { return _speed; }
      set { _speed = value; }
    }

    public DomainEntity GetElement(int x, int y) {
      return Matrix[x, y];
    }

    public DomainEntity GetShoot(int x, int y, int z) {
      return GetElement(x, y).Shoots[z];
    }
    
    public DomainEntity GetPowerUp(int x, int y, int z)
    {
      DomainEntity entity = null;
      var powerUps = GetElement(x, y).PowerUps;
      if(powerUps.Count > 0)
        entity = powerUps[z];
      return  entity;
    }

    public void SetElement(int x, int y, DomainEntity entityResult) {
      Matrix[x, y] = entityResult;
    }

    public void SetShoot(int x, int y, int z, DomainEntity result) {
      Matrix[x, y].Shoots[z] = result;
    }
    
    public void SetPowerUp(int x, int y, int z, DomainEntity result) {
      Matrix[x, y].PowerUps[z] = result;
    }

    public int GetAmount(int x, int y) {
      return GetElement(x, y) != null ? GetElement(x, y).Amount : 0;
    }

    public int GetDamage(int x, int y) {
      return GetElement(x, y).Damage;
    }

  }
}